(ns model.simulation
  (:import (java.awt Color Dimension)
  (javax.swing JPanel JFrame JOptionPane)
  (java.awt.event  KeyListener))
  (:use clojure.contrib.import-static))

(require ['model.object :as 'object])
(require ['model.vector3D :as 'vector3D])
(require ['model.vector3D :as 'position])

(def center (position/make 400 400 0))

(defstruct controls :zoom :center)

(def number-of-iteration (ref  0))
(def start-time (ref  (System/currentTimeMillis)))

(defn mass-size [{m :masa}]
  (Math/sqrt m))

(defn draw-object [g obj controls]
  (let [
    mag (:zoom controls)
    x-offset (- (:x center) (* mag (:x center)))
    y-offset (- (:y center) (* mag (:y center)))
    x (+ x-offset (* mag (:x (:pozicija obj))))
    y (+ y-offset (* mag (:y (:pozicija obj))))
    radius (max 2 (* mag (mass-size obj)))
    radius_2 (/ radius 2)
   ]
    (.setColor g Color/black)
    (.fillOval g (- x radius_2) (- y radius_2) radius radius)))

(defn draw-all-objects [g objects controls]
    (let [
        prvam (first objects)
       
        ]
        (doseq [obj objects]
            (draw-object g obj controls))
        
        (if (> @number-of-iteration 0) 
            (let [ iteration-time (float (/ (- (System/currentTimeMillis) @start-time) @number-of-iteration))]
            (.drawString g (format "Srednja brzina ciklusa %f ms" iteration-time) 20 20)))
        (.drawString g (format "Taster q za izlaz") 580 785)))

(defn move-sim [objects controls]
  (dosync
    (alter objects #(object/move-all %)))
  (dosync (alter number-of-iteration + 1 ))
  )

(defn- quit-key? [c]
    (= \q c))

(defn- plus-key? [c]
    (= \+ c))

(defn- minus-key? [c]
    (= \- c))

(defn handle-key [key controls]
  (cond
    (quit-key? key) (System/exit 1)
    (plus-key? key) (dosync (alter controls #(assoc % :zoom (* 2 (:zoom @controls)))))
    (minus-key? key) (dosync (alter controls #(assoc % :zoom (* 0.5 (:zoom @controls)))))))

(defn panel-sim [frame objects controls]
  (proxy [JPanel KeyListener] []
    (paintComponent [g]
        (proxy-super paintComponent g)
        (draw-all-objects g @objects @controls))
    (keyPressed [e]
      (handle-key (.getKeyChar e) controls)
      (.repaint this))
    (getPreferredSize []
      (Dimension. 800 800))
    (keyReleased [e])
    (keyTyped [e])
    )
  )

(defn random-velocity [p]
  (let [
    sd (position/distance p center)
    v (Math/sqrt (/ 1 sd))
    direction (vector3D/rotateXY (vector3D/unit (vector3D/sub p center)))
    ]
    (vector3D/s-mul direction (+ (rand 0.01) (* v 13.5)))))

(defn random-position []
  (let [
    r (rand 350)
    gama (rand (* 2 Math/PI))
    ]
    (position/add center (position/make (* r (Math/cos gama)) (* r (Math/sin gama)) 0))))

(defn random-object []
  (let [

    p (random-position)
    ]
    (object/make p (rand 1) (random-velocity p) (vector3D/make) (str "masa"))
    )
  )

(defn create-sim []
  (let [

   sun (random-object)
   ]
    (loop [objects [sun] n 500]
      (if (zero? n)
        objects
        (recur (conj objects (random-object)) (dec n))))))

(defn frame-sim []
  (let [
    controls (ref (struct-map controls
      :zoom 1.0
      :center center))
    objects (ref (create-sim))
    frame (JFrame. "Gravity")
    panel (panel-sim frame objects controls)
   ]

    (doto panel
      (.setFocusable true)
      (.addKeyListener panel))
    (doto frame
      (.add panel)
      (.pack)
      (.setVisible true)
      (.setDefaultCloseOperation JFrame/EXIT_ON_CLOSE))
    (while true
      (move-sim objects @controls)
      (.repaint panel))))

(defn run-sim []
  (frame-sim))


